﻿/*************************************************************************************
 * 文 件 名:   HK_SlidePage
 * 
 * 描    述:   图片轮播展示功能脚本
 * 
 * 版    本：  V1.1
 * 创 建 者：  京产肠饭、谭潇杰
 * 创建时间：  2021/12/23
 * 链   接：  https://gitee.com/JingChanChangFan/hk_-unity-tools
*************************************************************************************/

using System.Collections.Generic;
using UnityEngine.EventSystems;
using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;

[RequireComponent(typeof(RectTransform))]
public class HK_SlidePage : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
{
    public enum MoveType
    {
        Loop,         //循环
        PingPong,     //来回往复
    }

    public enum MoveDir
    {
        Left,
        Right,
    }

    [Header("切换方式："), SerializeField] MoveType moveType = MoveType.PingPong;

    [Header("图集父物体："), SerializeField] RectTransform content;
    GridLayoutGroup grid;

    [Header("上一页按钮："), SerializeField] Button lastPage_Btn;
    [Header("下一页按钮："), SerializeField] Button nextPage_Btn;

    [Header("页码单选ToggleGroup："), SerializeField] ToggleGroup pageToggleGroup;
    List<Toggle> pageToggleList;

    [Header("自动轮播时长："), SerializeField] float pageStayTime = 2.0f;

    [Header("是否自动轮播："), SerializeField] bool isAutoSlide = false;

    [Header("是否允许拖动切页："), SerializeField] bool isAllowDrag = true;
    bool isDraging = false;

    [Header("是否启用切页动画："), SerializeField] bool isUseAnim = false;
    bool isAniming = false;

    // 自动轮播方向，-1表示向左，1表示向右
    MoveDir moveDir = MoveDir.Right;

    // 最大页码
    int maxPageIndex = 0;
    // 当前显示页的页码，下标从0开始
    int curPageIndex = 0;
    public int CurPageIndex
    {
        get { return curPageIndex; }
        set
        {
            curPageIndex = value;

            if (curPageIndex <= 0)
            {
                curPageIndex = 0;

                lastPage_Btn.gameObject.SetActive(false);
                nextPage_Btn.gameObject.SetActive(true);
            }
            else if (curPageIndex >= maxPageIndex)
            {
                if (moveType == MoveType.PingPong)
                    curPageIndex = maxPageIndex;

                lastPage_Btn.gameObject.SetActive(true);
                nextPage_Btn.gameObject.SetActive(false);
            }
            else
            {
                lastPage_Btn.gameObject.SetActive(true);
                nextPage_Btn.gameObject.SetActive(true);
            }
        }
    }

    float recordTime = 0f;

    List<float> childItemPosX_List = new List<float>();

    //如果是Loop 判定当前是否已经实例化出来
    bool isAddChild = false;

    void Awake()
    {
        grid = content.GetComponent<GridLayoutGroup>();

        // 根据GridLayout初始化所有图的初始位置  
        int childCount = content.transform.childCount;
        float cellSizeX = grid.cellSize.x;
        float spacingX = grid.spacing.x;
        float posX = -cellSizeX * 0.5f;

        childItemPosX_List.Clear();
        childItemPosX_List.Add(posX);

        for (int i = 1; i <= childCount; i++)
        {
            //如果是Loop，多计算一个位置出来
            if (moveType != MoveType.Loop && i == childCount)
                continue;

            posX -= cellSizeX + spacingX;
            childItemPosX_List.Add(posX);
        }

        lastPage_Btn.onClick.AddListener(() =>
        {
            CurPageIndex--;
            SwitchToPageNum();
        });

        nextPage_Btn.onClick.AddListener(() =>
        {
            CurPageIndex++;
            SwitchToPageNum();
        });

        if (pageToggleGroup.transform.childCount > 0)
        {
            pageToggleList = new List<Toggle>();

            for (int i = 0; i < pageToggleGroup.transform.childCount; i++)
            {
                Toggle childToggle = pageToggleGroup.transform.GetChild(i).GetComponent<Toggle>();

                pageToggleList.Add(childToggle);

                int targetPageNum = i;

                childToggle.onValueChanged.AddListener(isOn =>
                {
                    if (!isOn)
                        return;

                    try
                    {
                        if (EventSystem.current.currentSelectedGameObject != childToggle.gameObject)
                            return;

                        CurPageIndex = targetPageNum;
                        SwitchToPageNum();
                    }
                    catch
                    {

                    }
                });
            }

            maxPageIndex = pageToggleList.Count - 1;
        }

        CurPageIndex = 0;
    }

    void Update()
    {
        if (!isAutoSlide || isDraging)
            return;

        if (Time.time > recordTime + pageStayTime)
        {
            recordTime = Time.time;

            // 如果是PingPong运动模式，则在运动到两头的时候改变方向
            if (moveType == MoveType.PingPong)
            {
                if (CurPageIndex == 0)
                    moveDir = MoveDir.Right;
                else if (CurPageIndex == maxPageIndex)
                    moveDir = MoveDir.Left;
            }

            if (moveDir == MoveDir.Left)
            {
                CurPageIndex--;
            }
            else if (moveDir == MoveDir.Right)
            {
                CurPageIndex++;
            }

            SwitchToPageNum();
        }
    }

    /// <summary>
    /// 切换至某页
    /// </summary>
    void SwitchToPageNum()
    {
        Vector3 pos = content.localPosition;

        if (moveType == MoveType.Loop && CurPageIndex == maxPageIndex)
            AddChildTempItem();

        if (isUseAnim)
        {
            if (moveType == MoveType.Loop && CurPageIndex > maxPageIndex)  //如果移动到最后
            {
                isAniming = true;
                content.DOLocalMoveX(childItemPosX_List[CurPageIndex], 0.5f)
                    .OnComplete(() =>
                    {
                        content.localPosition = new Vector3(childItemPosX_List[0], pos.y, pos.z);
                        isAniming = false;
                    });
                CurPageIndex = 0;
            }
            else
            {
                isAniming = true;
                content.DOLocalMoveX(childItemPosX_List[CurPageIndex], 0.5f)
                    .OnComplete(() => isAniming = false);
            }
        }
        else
        {
            if (moveType == MoveType.Loop && CurPageIndex > maxPageIndex) //移动到最后
            {
                content.localPosition = new Vector3(childItemPosX_List[0], pos.y, pos.z);
                CurPageIndex = 0;
            }
            else
            {
                content.localPosition = new Vector3(childItemPosX_List[CurPageIndex], pos.y, pos.z);
            }
        }

        recordTime = Time.time;//重新计时
        pageToggleList[CurPageIndex].isOn = true;
    }

    void AddChildTempItem()
    {
        if (!isAddChild)
        {
            Instantiate(content.GetChild(0).gameObject, content.transform);
            isAddChild = true;
        }
    }

    Vector3 originDragPos = Vector3.zero;

    public void OnPointerDown(PointerEventData eventData)
    {
        if (!isAllowDrag || isAniming)
            return;

        if (eventData.button != PointerEventData.InputButton.Left)
            return;

        isDraging = true;
        originDragPos = eventData.position;
    }

    public void OnPointerUp(PointerEventData eventData)
    {
        if (isAniming)
            return;

        Vector3 desDragPos = eventData.position;

        if (desDragPos.x > originDragPos.x)
        {
            CurPageIndex--;
        }
        else
        {
            CurPageIndex++;
        }

        SwitchToPageNum();

        isDraging = false;
    }
}
